﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography.X509Certificates;
using System.Windows.Forms;
using System.Net;
using System.Net.Security;
using System.IO;
using System.Data;
using NBear.Mapping;
using System.Xml;
using System.Collections;

namespace CTIClassLibrary
{
    public class PaymentEntity_CITIC
    {
        /// <summary>
        /// 卡号
        /// </summary>
        public string PAN;
        /// <summary>
        /// 金额
        /// </summary>
        public string transAmount;
        /// <summary>
        /// 证件号码
        /// </summary>
        public string IDNo;
        /// <summary>
        /// 主叫号码
        /// </summary>
        public string Phone;
        /// <summary>
        /// 订单号
        /// </summary>
        public int orderNo;
        public string posTime;
        /// <summary>
        /// 流水号
        /// </summary>
        public string posID;
        public string expiredDate;
        public static string terminalID;
        public static string merchantID;
        public static string merchantName;
        public static string password;
        /// <summary>
        /// 批号
        /// </summary>
        public string batchNo;
        public string cvv2;
        /// <summary>
        /// 货币类型
        /// </summary>
        public string currCode = "156";
        /// <summary>
        /// 分期数
        /// </summary>
        public string dividedNum = "00";
        public string productType = "000000";
    }

    /// <summary>
    /// 中信银行支付类
    /// </summary>
    public class BANK_CITIC
    {
        public static WebReferenceCITIC_BANK.PaymentServicesService CITIC_BANK = new WebReferenceCITIC_BANK.PaymentServicesService();
        public static X509Certificate2 cert = new X509Certificate2(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, XMLConfig.Operation.GetSettings().CiticCertFile), XMLConfig.Operation.GetSettings().CiticCertPassword);

        public PaymentEntity_CITIC PaymentEntity = new PaymentEntity_CITIC();
        public string XMLSent;
        public string XMLReceived;
        public string ErrorMsg;

        /// <summary>
        /// 初始化
        /// 只需执行一次,将被该类的所有实例共享
        /// </summary>
        public void InitializeSecurity()
        {
            ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
            CITIC_BANK.CookieContainer = new CookieContainer();
            CITIC_BANK.ClientCertificates.Add(BANK_CITIC.cert);

            XMLConfig.XMLSettings xmlConfig = XMLConfig.Operation.GetSettings();
            PaymentEntity_CITIC.terminalID = xmlConfig.TerminalID;
            PaymentEntity_CITIC.merchantID = xmlConfig.MerchantID;
            PaymentEntity_CITIC.merchantName = xmlConfig.MerchantName;
            PaymentEntity_CITIC.password = xmlConfig.Password;
        }

        private bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {
            return true;
        }

        /// <summary>
        /// 撤销支付（冲正，不参与结算和对账）
        /// </summary>
        /// <param name="orderID"></param>
        public void PaymentReversal(string orderID)
        {
            #region xml字符串
            string xml = @"<?xml version=""1.0"" encoding=""GBK""?>
<message method=""dividedPaymentReversal"" type=""request"">
        <infoType>0420</infoType>
        <pan>{0}</pan>
        <processCode></processCode>
        <transAmt>{1}</transAmt>
        <posTime>{2}</posTime>
        <posID>{3}</posID>
        <transTime></transTime>
        <transDate></transDate>
        <expiredDate>{4}</expiredDate>
        <inputType>021</inputType>
        <cardSerialNo></cardSerialNo>
        <posConditionCode>01</posConditionCode>
        <secondTrack></secondTrack>
        <thirdTrack></thirdTrack>
        <systemRefCode></systemRefCode>
        <authorizeCode></authorizeCode>
        <orgPosID>{14}</orgPosID>
        <retCode></retCode>
        <terminalID>{5}</terminalID>
        <merchantID>{6}</merchantID>
        <merchantName>{7}</merchantName>
        <commentRes></commentRes>
        <currCode>{10}</currCode>
        <passwdMac></passwdMac>
        <securityInfo></securityInfo>
        <icDataField ></icDataField >
        <termAbilities></termAbilities>
        <chIdNum>{13}</chIdNum>
        <chName></chName>
        <chMobile></chMobile>
        <dynamicPwd></dynamicPwd>
        <personalMsg></personalMsg>
        <batchNo>{8}</batchNo>
        <dividedNum>{11}</dividedNum>
        <productType>{12}</productType>
        <cvv2>{9}</cvv2>
        <reserved1></reserved1>
        <reserved2></reserved2>
</message>";
            #endregion

            DataSet ds = Common.DB.Select(Tables.t_CITIC_Transfer)
                .Where(Tables.t_CITIC_Transfer.OrderID == orderID)
                .ToDataSet();

            if (ds.Tables[0].Rows.Count > 0)
            {
                Model.T_CITIC_Transfer tran = ObjectConvertor.ToObject<Model.T_CITIC_Transfer>(ds.Tables[0].Rows[0]);
                string transAmountOrig = Common.CITICAmountFormat(tran.TransAmt);
                string dtNow = DateTime.Now.ToString("yyyyMMddHHmmss");
                string traceNo = Common.TraceNo_CITIC;

                xml = string.Format(xml, tran.PAN, transAmountOrig,
                    dtNow, traceNo, tran.ExpiredDate,
                    tran.TerminalID, tran.MerchantID, tran.MerchantName, Common.BatchNo_CITIC_Pay, tran.CVV2,
                    tran.CurrCode, tran.DividedMonths, tran.ProductCode, tran.IDNo, tran.PosID);
                this.XMLSent = xml;

                for (int i = 0; i < 3; i++)
                {
                    xml = CITIC_BANK.dividedPaymentReversal(XMLSent);
                    this.XMLReceived = xml;
                    string retCode = Common.GetXMLElementValue(xml, "retCode");

                    if (retCode == "6666661")//未登陆，请登陆
                    {
                        (new BANK_CITIC()).Login();
                        continue;
                    }

                    if (retCode == "0000000")//撤销成功
                    {
                        try
                        {
                            Common.DB.Update(Tables.t_CITIC_Transfer)
                                .AddColumn(Tables.t_CITIC_Transfer.TransType, "撤销")
                                .Where(Tables.t_CITIC_Transfer.OrderID == orderID)
                                .Execute();
                            string msg = string.Format("撤销成功！订单号：{0}", orderID);
                            LogIt(msg, "撤销");
                        }
                        catch (Exception e1)
                        {
                            this.ErrorMsg += "撤销成功！但是生成日志失败，错误是：" + e1.Message;
                        }
                    }
                    else
                    {
                        this.ErrorMsg = string.Format("撤销失败 订单号是:{0} 返回码是:{1} 反馈信息是:{2}", orderID, retCode, Common.GetXMLElementValue(xml, "commentRes"));
                        LogIt(this.ErrorMsg, "撤销");
                    }

                    break;
                }
            }
            else
            {
                this.ErrorMsg = "该订单不存在！订单号：{0}";
                this.ErrorMsg = string.Format(this.ErrorMsg, orderID);
                LogIt(this.ErrorMsg, "撤销");
            }
        }

        /// <summary>
        /// 退款（不需要参与结算）
        /// </summary>
        /// <param name="orderID"></param>
        public void PaymentRefund(string orderID, decimal amount)
        {
            #region xml字符串
            string xml = @"<?xml version=""1.0"" encoding=""GBK""?>
<message method=""hirePurchaseReturn"" type=""request"">
        <infoType>0200</infoType>
        <pan>{0}</pan>
        <processCode></processCode>
        <orgTransAmt>{15}</orgTransAmt>
        <orgBatchNo>{16}</orgBatchNo>
        <transAmt>{1}</transAmt>
        <posTime>{2}</posTime>
        <posID>{3}</posID>
        <transTime></transTime>
        <transDate></transDate>
        <expiredDate>{4}</expiredDate>
        <inputType>021</inputType>
        <cardSerialNo></cardSerialNo>
        <posConditionCode>01</posConditionCode>
        <secondTrack></secondTrack>
        <thirdTrack></thirdTrack>
        <systemRefCode></systemRefCode>
        <authorizeCode>{17}</authorizeCode>
        <orgPosID>{14}</orgPosID>
        <retCode></retCode>
        <terminalID>{5}</terminalID>
        <merchantID>{6}</merchantID>
        <merchantName>{7}</merchantName>
        <commentRes></commentRes>
        <currCode>{10}</currCode>
        <passwdMac></passwdMac>
        <securityInfo></securityInfo>
        <icDataField ></icDataField >
        <termAbilities></termAbilities>
        <chIdNum>{13}</chIdNum>
        <chName></chName>
        <chMobile></chMobile>
        <dynamicPwd></dynamicPwd>
        <personalMsg></personalMsg>
        <batchNo>{8}</batchNo>
        <dividedNum>{11}</dividedNum>
        <productType>{12}</productType>
        <cvv2>{9}</cvv2>
        <reserved1></reserved1>
        <reserved2></reserved2>
</message>";
            #endregion

            DataSet ds = Common.DB.Select(Tables.t_CITIC_Transfer)
                .Where(Tables.t_CITIC_Transfer.OrderID == orderID)
                .ToDataSet();

            if (ds.Tables[0].Rows.Count > 0)
            {
                Model.T_CITIC_Transfer tran = ObjectConvertor.ToObject<Model.T_CITIC_Transfer>(ds.Tables[0].Rows[0]);
                string transAmountOrig = Common.CITICAmountFormat(tran.TransAmt);
                string transAmount = Common.CITICAmountFormat(amount);
                string dtNow = DateTime.Now.ToString("yyyyMMddHHmmss");
                string traceNo = Common.TraceNo_CITIC;

                xml = string.Format(xml, tran.PAN, transAmount,
                    dtNow, traceNo, tran.ExpiredDate,
                    tran.TerminalID, tran.MerchantID, tran.MerchantName, Common.BatchNo_CITIC_Refund, tran.CVV2,
                    tran.CurrCode, tran.DividedMonths, tran.ProductCode, tran.IDNo, tran.PosID, transAmountOrig, tran.BatchNo, tran.AuthorizeCode);
                this.XMLSent = xml;

                for (int i = 0; i < 3; i++)
                {
                    xml = CITIC_BANK.hirePurchaseReturn(this.XMLSent);
                    this.XMLReceived = xml;
                    string retCode = Common.GetXMLElementValue(xml, "retCode");

                    if (retCode == "6666661")//未登陆，请登陆
                    {
                        (new BANK_CITIC()).Login();
                        continue;
                    }

                    if (retCode == "0000000")//退款成功
                    {
                        try
                        {
                            Common.BatchNo_CITIC_Refund = "add";
                        }
                        catch (Exception ex)
                        {
                            string msg = string.Format("退款批次号自增失败！错误是:{0}", ex.Message);
                            LogIt(msg, "退款");
                        }

                        try
                        {
                            Common.DB.Insert(Tables.t_CITIC_Transfer)
                                .AddColumn(Tables.t_CITIC_Transfer.TransType, "退款")
                                .AddColumn(Tables.t_CITIC_Transfer.OrderID, tran.OrderID)
                                .AddColumn(Tables.t_CITIC_Transfer.BatchNo, Common.BatchNo_CITIC_Refund)
                                .AddColumn(Tables.t_CITIC_Transfer.CurrCode, tran.CurrCode)
                                .AddColumn(Tables.t_CITIC_Transfer.CVV2, tran.CVV2)
                                .AddColumn(Tables.t_CITIC_Transfer.DividedMonths, tran.DividedMonths)
                                .AddColumn(Tables.t_CITIC_Transfer.ExpiredDate, tran.ExpiredDate)
                                .AddColumn(Tables.t_CITIC_Transfer.MerchantID, tran.MerchantID)
                                .AddColumn(Tables.t_CITIC_Transfer.MerchantName, tran.MerchantName)
                                .AddColumn(Tables.t_CITIC_Transfer.IDNo, tran.IDNo)
                                .AddColumn(Tables.t_CITIC_Transfer.PAN, tran.PAN)
                                .AddColumn(Tables.t_CITIC_Transfer.PosID, traceNo)
                                .AddColumn(Tables.t_CITIC_Transfer.PosTime, dtNow)
                                .AddColumn(Tables.t_CITIC_Transfer.ProductCode, tran.ProductCode)
                                .AddColumn(Tables.t_CITIC_Transfer.TerminalID, tran.TerminalID)
                                .AddColumn(Tables.t_CITIC_Transfer.TransAmt, 0 - amount)
                                .AddColumn(Tables.t_CITIC_Transfer.AuthorizeCode, tran.AuthorizeCode)
                                .AddColumn(Tables.t_CITIC_Transfer.SystemRefCode, tran.SystemRefCode)

                                .AddColumn(Tables.t_CITIC_Transfer.CustomerName, tran.CustomerName)
                                .AddColumn(Tables.t_CITIC_Transfer.CustomerPhone, tran.CustomerPhone)
                                .AddColumn(Tables.t_CITIC_Transfer.CityOrig, tran.CityOrig)
                                .AddColumn(Tables.t_CITIC_Transfer.CityDest, tran.CityDest)
                                .AddColumn(Tables.t_CITIC_Transfer.TakeOff, tran.TakeOff)
                                .AddColumn(Tables.t_CITIC_Transfer.Flight, tran.Flight)
                                .AddColumn(Tables.t_CITIC_Transfer.Passengers, tran.Passengers)
                                .Execute();

                            string msg = string.Format("退款成功！订单号是:{0} 金额是:{1}", orderID, amount);
                            LogIt(msg, "退款");
                        }
                        catch (Exception e1)
                        {
                            this.ErrorMsg += string.Format("退款成功！但是生成日志失败 订单号是：{0} 金额是：{1} 错误是：{2}", orderID, amount, e1.Message);
                            LogIt(this.ErrorMsg, "退款");
                        }
                    }
                    else
                    {
                        this.ErrorMsg = string.Format("退款失败！订单号是:{0} 金额是:{1} 返回码是:{2} 反馈信息是:{3}", orderID, amount, retCode, Common.GetXMLElementValue(xml, "commentRes"));
                        LogIt(this.ErrorMsg, "退款");
                    }

                    break;
                }
            }
            else
            {
                this.ErrorMsg = "该订单不存在！订单号：{0}，退款金额：{1}";
                this.ErrorMsg = string.Format(this.ErrorMsg, orderID, amount);
                LogIt(this.ErrorMsg, "退款");
            }
        }

        public void Pay()
        {
            #region xml字符串
            string xml = @"<?xml version=""1.0"" encoding=""GBK""?>
<message method=""dividedPayment"" type=""request"">
        <infoType>0200</infoType>
        <pan>{0}</pan>
        <processCode></processCode>
        <transAmt>{1}</transAmt>
        <posTime>{2}</posTime>
        <posID>{3}</posID>
        <transTime></transTime>
        <transDate></transDate>
        <expiredDate>{4}</expiredDate>
        <inputType>021</inputType>
        <cardSerialNo></cardSerialNo>
        <posConditionCode>01</posConditionCode>
        <secondTrack></secondTrack>
        <thirdTrack></thirdTrack>
        <systemRefCode></systemRefCode>
        <authorizeCode></authorizeCode>
        <retCode></retCode>
        <terminalID>{5}</terminalID>
        <merchantID>{6}</merchantID>
        <merchantName>{7}</merchantName>
        <commentRes></commentRes>
        <currCode>{10}</currCode>
        <passwdMac></passwdMac>
        <securityInfo></securityInfo>
        <icDataField ></icDataField >
        <termAbilities></termAbilities>
        <chIdNum>{13}</chIdNum>
        <chName>{14}</chName>
        <chMobile></chMobile>
        <dynamicPwd></dynamicPwd>
        <personalMsg></personalMsg>
        <batchNo>{8}</batchNo>
        <dividedNum>{11}</dividedNum>
        <productType>{12}</productType>
        <dividedFee></dividedFee>
        <totalAmt></totalAmt>
        <dividedAmt></dividedAmt>
        <cvv2>{9}</cvv2>
        <reserved1></reserved1>
        <reserved2></reserved2>
</message>";
            #endregion

            try
            {
                PaymentEntity_CITIC pay = this.PaymentEntity;

                if (string.IsNullOrEmpty(pay.Phone))
                {
                    pay.Phone = Common.DB.Select(Tables.t_CITIC_CallBackHistory, Tables.t_CITIC_CallBackHistory.PhoneNo)
                                        .Where(Tables.t_CITIC_CallBackHistory.OrderID == pay.orderNo)
                                        .ToScalar().ToString();
                }

                if (string.IsNullOrEmpty(pay.Phone))
                {
                    this.ErrorMsg = string.Format("主叫号码为空？无法支付！ 金额：{0}", pay.transAmount);
                    this.LogIt(this.ErrorMsg, "支付");
                    return;
                }

                WebService.TicketWebService tws = new WebService.TicketWebService();
                string xmlCus;

                try
                {
                    xmlCus = tws.GetCustomerByPhone(pay.Phone);
                }
                catch (Exception e2)
                {
                    this.ErrorMsg = "获取客户资料失败 电话：{0} 订单号：{1} 支付金额：{2} 错误信息：{3}";
                    this.ErrorMsg = string.Format(this.ErrorMsg, pay.Phone, pay.orderNo, pay.transAmount, e2.Message);
                    LogIt(this.ErrorMsg, "支付");
                    return;
                }

                DataEntity.XMLSchema.Customers customer = DataEntity.XMLSchema.xml_BaseClass.LoadXml<DataEntity.XMLSchema.Customers>(xmlCus);
                if (customer == null)
                {
                    this.ErrorMsg = string.Format("未找到来电客户资料！ 电话：{0} 金额：{1}", pay.Phone, pay.transAmount);
                    LogIt(this.ErrorMsg, "支付");
                    return;
                }
                pay.IDNo = customer.CardID;

                xml = string.Format(xml, pay.PAN, pay.transAmount,
                        pay.posTime, pay.posID, pay.expiredDate,
                        PaymentEntity_CITIC.terminalID, PaymentEntity_CITIC.merchantID, PaymentEntity_CITIC.merchantName, pay.batchNo, pay.cvv2,
                        pay.currCode, pay.dividedNum, pay.productType, pay.IDNo, customer.CustomerName);
                this.XMLSent = xml;

                for (int i = 0; i < 3; i++)
                {
                    try
                    {
                        xml = CITIC_BANK.dividedPayment(this.XMLSent);
                    }
                    catch (Exception e1)
                    {
                        this.ErrorMsg = "支付失败 电话：{0} 订单号：{1} 支付金额：{2} 错误信息：{3}";
                        this.ErrorMsg = string.Format(this.ErrorMsg, pay.Phone, pay.orderNo, pay.transAmount, e1.Message);
                        LogIt(this.ErrorMsg, "支付");
                        continue;
                    }

                    this.XMLReceived = xml;
                    string retCode = Common.GetXMLElementValue(xml, "retCode");

                    if (retCode == "6666661")//未登陆，请登陆
                    {
                        (new BANK_CITIC()).Login();
                        continue;
                    }
                    
                    if (retCode == "0000000")//支付成功
                    {
                        //通知b2c系统订单的已支付
                        decimal amount = decimal.Parse(pay.transAmount) / 100;
                        string ret = tws.PaymentChecked(pay.orderNo, amount);

                        switch (ret)
                        {
                            case "1":
                                break;
                            case "0":
                                this.ErrorMsg = string.Format("修改订单状态失败！ 电话：{0} 金额：{1}", pay.Phone, pay.transAmount);
                                LogIt(this.ErrorMsg, "支付");
                                break;
                            case "-1":
                                this.ErrorMsg = string.Format("修改订单状态失败！原因：没有找到对应的订单号。 电话：{0} 金额：{1}", pay.Phone, pay.transAmount);
                                LogIt(this.ErrorMsg, "支付");
                                break;
                        }

                        //客户基本资料
                        try
                        {
                            string authorizeCode = Common.GetXMLElementValue(xml, "authorizeCode");
                            string systemRefCode = Common.GetXMLElementValue(xml, "systemRefCode");
                            string transTime = Common.GetXMLElementValue(xml, "transTime");
                            string transDate = Common.GetXMLElementValue(xml, "transDate");

                            string takeOffCity = "";
                            string arrivedCity = "";
                            string takeOffDay = "1900-1-1";
                            string airlineCode = "";
                            string passengerNames = "";

                            foreach (DataEntity.XMLSchema.AboutTicketOrder order in customer.TicketOrders)
                            {
                                if(order.TicketOrderID == pay.orderNo.ToString())
                                {
                                    takeOffCity = order.TakeOffCity;
                                    arrivedCity = order.ArrivedCity;
                                    takeOffDay = order.TakeOffDay;
                                    airlineCode = order.AirlineCode;
                                    passengerNames = order.PassengerNames;
                                    break;
                                }
                            }

                            Common.DB.Insert(Tables.t_CITIC_Transfer)
                                .AddColumn(Tables.t_CITIC_Transfer.TransType, "支付")
                                .AddColumn(Tables.t_CITIC_Transfer.OrderID, pay.orderNo)
                                .AddColumn(Tables.t_CITIC_Transfer.BatchNo, pay.batchNo)
                                .AddColumn(Tables.t_CITIC_Transfer.CurrCode, pay.currCode)
                                .AddColumn(Tables.t_CITIC_Transfer.CVV2, pay.cvv2)
                                .AddColumn(Tables.t_CITIC_Transfer.DividedMonths, pay.dividedNum)
                                .AddColumn(Tables.t_CITIC_Transfer.ExpiredDate, pay.expiredDate)
                                .AddColumn(Tables.t_CITIC_Transfer.MerchantID, PaymentEntity_CITIC.merchantID)
                                .AddColumn(Tables.t_CITIC_Transfer.MerchantName, PaymentEntity_CITIC.merchantName)
                                .AddColumn(Tables.t_CITIC_Transfer.IDNo, pay.IDNo)
                                .AddColumn(Tables.t_CITIC_Transfer.PAN, pay.PAN)
                                .AddColumn(Tables.t_CITIC_Transfer.PosID, pay.posID)
                                .AddColumn(Tables.t_CITIC_Transfer.PosTime, pay.posTime)
                                .AddColumn(Tables.t_CITIC_Transfer.ProductCode, pay.productType)
                                .AddColumn(Tables.t_CITIC_Transfer.TerminalID, PaymentEntity_CITIC.terminalID)
                                .AddColumn(Tables.t_CITIC_Transfer.TransAmt, decimal.Parse(pay.transAmount) / 100)
                                .AddColumn(Tables.t_CITIC_Transfer.AuthorizeCode, authorizeCode)
                                .AddColumn(Tables.t_CITIC_Transfer.SystemRefCode, systemRefCode)
                                .AddColumn(Tables.t_CITIC_Transfer.TransDate, transDate)
                                .AddColumn(Tables.t_CITIC_Transfer.TransTime, transTime)
                                .AddColumn(Tables.t_CITIC_Transfer.CustomerName, customer.CustomerName)
                                .AddColumn(Tables.t_CITIC_Transfer.CustomerPhone, pay.Phone)
                                //航班明细失败
                                .AddColumn(Tables.t_CITIC_Transfer.CityOrig, takeOffCity)
                                .AddColumn(Tables.t_CITIC_Transfer.CityDest, arrivedCity)
                                .AddColumn(Tables.t_CITIC_Transfer.TakeOff, takeOffDay)
                                .AddColumn(Tables.t_CITIC_Transfer.Flight, airlineCode)
                                .AddColumn(Tables.t_CITIC_Transfer.Passengers, passengerNames)
                                .Execute();
                        }
                        catch (Exception e1)
                        {
                            string err = string.Format("生成消费明细失败，仅生成基本消费信息。错误是：{0} 电话：{1} 金额：{2}", e1.Message, pay.Phone, pay.transAmount);
                            LogIt(err, "支付");
                            this.ErrorMsg += err;

                            try
                            {
                                //航班明细失败，只保存基本信息
                                Common.DB.Insert(Tables.t_CITIC_Transfer)
                                        .AddColumn(Tables.t_CITIC_Transfer.TransType, "支付")
                                        .AddColumn(Tables.t_CITIC_Transfer.OrderID, pay.orderNo)
                                        .AddColumn(Tables.t_CITIC_Transfer.BatchNo, pay.batchNo)
                                        .AddColumn(Tables.t_CITIC_Transfer.CurrCode, pay.currCode)
                                        .AddColumn(Tables.t_CITIC_Transfer.CVV2, pay.cvv2)
                                        .AddColumn(Tables.t_CITIC_Transfer.DividedMonths, pay.dividedNum)
                                        .AddColumn(Tables.t_CITIC_Transfer.ExpiredDate, pay.expiredDate)
                                        .AddColumn(Tables.t_CITIC_Transfer.MerchantID, PaymentEntity_CITIC.merchantID)
                                        .AddColumn(Tables.t_CITIC_Transfer.MerchantName, PaymentEntity_CITIC.merchantName)
                                        .AddColumn(Tables.t_CITIC_Transfer.IDNo, pay.IDNo)
                                        .AddColumn(Tables.t_CITIC_Transfer.PAN, pay.PAN)
                                        .AddColumn(Tables.t_CITIC_Transfer.PosID, pay.posID)
                                        .AddColumn(Tables.t_CITIC_Transfer.PosTime, pay.posTime)
                                        .AddColumn(Tables.t_CITIC_Transfer.ProductCode, pay.productType)
                                        .AddColumn(Tables.t_CITIC_Transfer.TerminalID, PaymentEntity_CITIC.terminalID)
                                        .AddColumn(Tables.t_CITIC_Transfer.TransAmt, decimal.Parse(pay.transAmount) / 100)
                                        .AddColumn(Tables.t_CITIC_Transfer.CustomerName, customer.CustomerName)
                                        .AddColumn(Tables.t_CITIC_Transfer.CustomerPhone, pay.Phone)
                                        .Execute();
                            }
                            catch (Exception e2)
                            {
                                string err2 = string.Format("生成基本消费信息失败，错误是：{0} 电话：{1} 金额：{2}", e2.Message, pay.Phone, pay.transAmount);
                                LogIt(err2, "支付");
                                this.ErrorMsg += err;
                            }
                        }

                        string msg = string.Format("支付成功！ 电话：{0} 订单号：{1} 支付金额：{2}", pay.Phone, pay.orderNo, pay.transAmount);
                        LogIt(msg, "支付");
                    }
                    else
                    {
                        this.ErrorMsg = "支付失败 电话：{0} 订单号：{1} 支付金额：{2},返回码是：{3} 反馈信息是：{4}";
                        this.ErrorMsg = string.Format(this.ErrorMsg, pay.Phone, pay.orderNo, pay.transAmount, retCode, Common.GetXMLElementValue(xml, "commentRes"));
                        LogIt(this.ErrorMsg, "支付");
                    }

                    break;
                }
            }
            catch (Exception ee)
            {
                LogIt(ee.Message, "支付");
                this.ErrorMsg += ee.Message;
            }
        }

        public void Login()
        {
            string xml = @"<?xml version=""1.0"" encoding=""GBK""?>
<message method=""login"" type=""request"">
	<infoType>0800</infoType>
	<posTime>{0}</posTime>
	<posID>{1}</posID>
	<transTime></transTime>
	<transDate></transDate>
	<retCode></retCode>
	<terminalID>{2}</terminalID>
	<merchantID>{3}</merchantID>
	<merchantName>{4}</merchantName>
	<password>{5}</password>
	<commentRes></commentRes>
	<resParam></resParam>
	<reserved></reserved>
</message>";
            DateTime dt = DateTime.Now;
            xml = string.Format(xml, dt.ToString("yyyyMMddHHmmss"), Common.TraceNo_CITIC,
                PaymentEntity_CITIC.terminalID, PaymentEntity_CITIC.merchantID, PaymentEntity_CITIC.merchantName, PaymentEntity_CITIC.password);
            this.XMLSent = xml;

            try
            {
                xml = CITIC_BANK.login(xml);
                this.XMLReceived = xml;
                string retCode = Common.GetXMLElementValue(xml, "retCode");

                if (retCode != "0000000")
                {
                    this.ErrorMsg = "登录失败,返回码是:" + retCode + " 反馈信息是:" + Common.GetXMLElementValue(xml, "commentRes");
                    LogIt(this.ErrorMsg, "登录");
                }
                else
                {
                    LogIt("成功登录银行网关！", "登录");
                }
            }
            catch (Exception ee)
            {
                this.ErrorMsg = ee.Message;
                LogIt("登录失败：" + this.ErrorMsg, "登录");
            }
        }

        public void ChangePassword(string newPass)
        {
            string xml = @"<?xml version=""1.0"" encoding=""GBK""?>
<message method=""changePassword"" type=""request"">
	<infoType>0800</infoType>
	<posTime>{0}</posTime>
	<posID>{1}</posID>
	<transTime></transTime>
	<transDate></transDate>
	<retCode></retCode>
	<terminalID>{2}</terminalID>
	<merchantID>{3}</merchantID>
	<merchantName>{4}</merchantName>
	<password>{5}</password>
	<commentRes></commentRes>
	<newPassword>{6}</newPassword>
	<reserved></reserved>
</message>";
            DateTime dt = DateTime.Now;
            xml = string.Format(xml, dt.ToString("yyyyMMddHHmmss"), Common.TraceNo_CITIC,
                PaymentEntity_CITIC.terminalID, PaymentEntity_CITIC.merchantID, PaymentEntity_CITIC.merchantName, PaymentEntity_CITIC.password, newPass);
            this.XMLSent = xml;

            try
            {
                xml = CITIC_BANK.changePassword(xml);
                this.XMLReceived = xml;
                string retCode = Common.GetXMLElementValue(xml, "retCode");

                if (retCode != "0000000")
                {
                    this.ErrorMsg = "修改密码失败,返回码是:" + retCode + " 反馈信息是:" + Common.GetXMLElementValue(xml, "commentRes");
                }
                else
                {
                    XMLConfig.XMLSettings xs = XMLConfig.Operation.GetSettings();
                    xs.Password = newPass;
                    XMLConfig.Operation.SaveSettings(xs);
                    PaymentEntity_CITIC.password = newPass;
                }
            }
            catch (Exception ee)
            {
                this.ErrorMsg = ee.Message;
            }
        }

        public void Logout()
        {
            string xml = @"<?xml version=""1.0"" encoding=""GBK""?>
<message method=""logout"" type=""request"">
	<infoType>0800</infoType>
	<posTime>{0}</posTime>
	<posID>{1}</posID>
	<transTime></transTime>
	<transDate></transDate>
	<retCode></retCode>
	<terminalID>{2}</terminalID>
	<merchantID>{3}</merchantID>
	<merchantName>{4}</merchantName>
	<password>{5}</password>
	<commentRes></commentRes>
	<resParam></resParam>
	<reserved></reserved>
</message>";
            DateTime dt = DateTime.Now;
            xml = string.Format(xml, dt.ToString("yyyyMMddHHmmss"), Common.TraceNo_CITIC,
                PaymentEntity_CITIC.terminalID, PaymentEntity_CITIC.merchantID, PaymentEntity_CITIC.merchantName, PaymentEntity_CITIC.password);
            this.XMLSent = xml;

            try
            {
                xml = CITIC_BANK.logout(xml);
                this.XMLReceived = xml;
                string retCode = Common.GetXMLElementValue(xml, "retCode");

                if (retCode != "0000000")
                {
                    this.ErrorMsg = "登出失败,返回码是:" + retCode + " 反馈信息是:" + Common.GetXMLElementValue(xml, "commentRes");
                }
            }
            catch (Exception ee)
            {
                this.ErrorMsg = ee.Message;
            }
        }

        public void GetQuestResult(string batchNo, DateTime dateStart, DateTime dateEnd)
        {
            string xml = @"<?xml version=""1.0"" encoding=""GBK""?>
<message method=""getQuestResult"" type=""request"">
	<infoType>0200</infoType>
	<posTime>{0}</posTime>
	<posID>{1}</posID>
	<transTime></transTime>
	<transDate></transDate>
	<retCode></retCode>
	<terminalID>{2}</terminalID>
	<merchantID>{3}</merchantID>
	<merchantName>{4}</merchantName>
	<batchNo>{5}</batchNo>
    <transBeginDate>{6}</transBeginDate>
	<transBeginTime>{7}</transBeginTime>
    <transEndDate>{8}</transEndDate>
	<transEndTime>{9}</transEndTime>
    <sequelFlag></sequelFlag>
    <offsetDate></offsetDate>
    <offsetTime></offsetTime>
    <dataSet></dataSet>
    <commentRes></commentRes>
	<reserved></reserved>
</message>";
            DateTime dt = DateTime.Now;
            xml = string.Format(xml, dt.ToString("yyyyMMddHHmmss"), Common.TraceNo_CITIC,
                PaymentEntity_CITIC.terminalID, PaymentEntity_CITIC.merchantID, PaymentEntity_CITIC.merchantName, batchNo, dateStart.ToString("yyyyMMdd"), "00000000", dateEnd.ToString("yyyyMMdd"), "23595900");
            this.XMLSent = xml;

            try
            {
                for (int i = 0; i < 3; i++)
                {
                    xml = CITIC_BANK.getQuestResult(xml);
                    this.XMLReceived = xml;
                    string retCode = Common.GetXMLElementValue(xml, "retCode");

                    if (retCode == "6666661")//未登陆，请登陆
                    {
                        (new BANK_CITIC()).Login();
                        continue;
                    }

                    if (retCode != "0000000")
                    {
                        this.ErrorMsg = "查询失败,返回码是:" + retCode + " 反馈信息是:" + Common.GetXMLElementValue(xml, "commentRes");
                    }

                    break;
                }
            }
            catch (Exception ee)
            {
                this.ErrorMsg = ee.Message;
            }
        }

        /// <summary>
        /// 仅允许结算一次，失败则只能走对账流程
        /// </summary>
        public void Settlement(string batchNo)
        {
            DataSet ds = Common.DB.Select(Tables.t_CITIC_Transfer,
    Tables.t_CITIC_Transfer.TransID.Count(),
    Tables.t_CITIC_Transfer.TransAmt.Sum())
    .Where(Tables.t_CITIC_Transfer.BatchNo == batchNo)
    .Where(Tables.t_CITIC_Transfer.TransType == "支付")
    .ToDataSet();
            string totalTrsCnt = ds.Tables[0].Rows[0][0].ToString();
            if (totalTrsCnt == "0")
            {
                this.ErrorMsg = "没有发现交易记录，无法结算！";
                return;
            }

            string xml = @"<?xml version=""1.0"" encoding=""GBK""?>
<message method=""settltment"" type=""request"">
	<infoType>0200</infoType>
	<posTime>{0}</posTime>
	<posID>{1}</posID>
	<transTime></transTime>
	<transDate></transDate>
	<retCode></retCode>
	<terminalID>{2}</terminalID>
	<merchantID>{3}</merchantID>
	<merchantName>{4}</merchantName>
	<batchNo>{5}</batchNo>
	<totalTrsCnt>{6}</totalTrsCnt>
	<sign>{7}</sign>
	<traSumAmt>{8}</traSumAmt>
	<successFlag></successFlag>
	<commentRes></commentRes>
	<reserved></reserved>
</message>";

            string traSumAmt = Common.CITICAmountFormat(Convert.ToDecimal(ds.Tables[0].Rows[0][1]));

            DateTime dt = DateTime.Now;
            xml = string.Format(xml, dt.ToString("yyyyMMddHHmmss"), Common.TraceNo_CITIC,
                PaymentEntity_CITIC.terminalID, PaymentEntity_CITIC.merchantID, PaymentEntity_CITIC.merchantName, batchNo,
               totalTrsCnt, "+", traSumAmt);
            this.XMLSent = xml;

            try
            {
                for (int i = 0; i < 3; i++)
                {
                    xml = CITIC_BANK.settltment(XMLSent);
                    this.XMLReceived = xml;
                    string retCode = Common.GetXMLElementValue(xml, "retCode");
                    //string retCount = Common.GetXMLElementValue(xml, "totalTrsCnt");//银行返回的条目

                    if (retCode == "6666661")//未登陆，请登陆
                    {
                        (new BANK_CITIC()).Login();
                        continue;
                    }

                    if (batchNo == Common.BatchNo_CITIC_Pay)//如果是历史批号，不自增
                    {
                        try
                        {
                            Common.BatchNo_CITIC_Pay = "add";//随便赋值均可，让批次号自动加 1，仅可结算一次，若不符合，进入对账流程
                        }
                        catch (Exception ex)
                        {
                            string msg = string.Format("批次号自增失败！错误是:{0}", ex.Message);
                            LogIt(msg, "结算");
                        }
                    }

                    if (retCode != "0000000")
                    {
                        this.ErrorMsg = "结算失败，返回码是：" + retCode + "，反馈信息是：" + Common.GetXMLElementValue(xml, "commentRes");
                        LogIt(this.ErrorMsg, "结算");
                    }
                    else
                    {
                        //if (totalTrsCnt == retCount)
                        {
                            //核对成功 A 已核对 B 核对失败 C
                            string successFlag = Common.GetXMLElementValue(xml, "successFlag");
                            successFlag = CheckFlag(successFlag);

                            switch (successFlag)
                            {
                                case "核对失败":
                                    string errorMsg = String.Format("批号 {0} 结算失败！", batchNo);
                                    LogIt(errorMsg, "结算");
                                    //CheckAccount(batchNo);
                                    break;
                                case "已核对":
                                    this.ErrorMsg = "该批次已核对";
                                    break;
                                case "核对成功":
                                    Common.hasSettled = true;
                                    Common.DB.Update(Tables.t_CITIC_Transfer)
                                                        .AddColumn(Tables.t_CITIC_Transfer.Flag, successFlag)
                                                        .Where(Tables.t_CITIC_Transfer.BatchNo == batchNo)
                                                        .Where(Tables.t_CITIC_Transfer.TransType == "支付")
                                                        .Execute();
                                    LogIt(String.Format("批号 {0} 结算成功！ 总金额：{1}", batchNo, decimal.Parse(traSumAmt) / 100), "结算");
                                    break;
                            }
                        }
                        //else
                        //{
                        //this.ErrorMsg = String.Format("批号 {0} 结算失败，条目数量不匹配！进入对账流程…", batchNo);
                        //LogIt(this.ErrorMsg, "结算");
                        //CheckAccount(batchNo);
                        //}
                    }

                    break;
                }
            }
            catch (Exception ee)
            {
                this.ErrorMsg = ee.Message;
            }
        }

        /// <summary>
        /// 对账，仅允许对账一次
        /// </summary>
        /// <param name="batchNo"></param>
        public void CheckAccount(string batchNo)
        {
            DataSet ds = Common.DB.Select(Tables.t_CITIC_Transfer)
                                    .Where(Tables.t_CITIC_Transfer.BatchNo == batchNo)
                                    .Where(Tables.t_CITIC_Transfer.TransType != "撤销")
                                    .ToDataSet();
            int totalTrsCnt = ds.Tables[0].Rows.Count;
            int totalBackup = totalTrsCnt;
            if (totalTrsCnt == 0)
            {
                this.ErrorMsg = "没有发现交易记录，无法对账！";
                return;
            }

            string xmlRequest = @"<?xml version=""1.0"" encoding=""GBK""?>
<message method=""checkAccount"" type=""request"">
	<infoType>0200</infoType>
	<posTime>{0}</posTime>
	<posID>{1}</posID>
	<transTime></transTime>
	<transDate></transDate>
	<retCode></retCode>
	<terminalID>{2}</terminalID>
	<merchantID>{3}</merchantID>
	<merchantName>{4}</merchantName>
	<batchNo>{5}</batchNo>
    <dataSet>$dataSet</dataSet>
	<terminalFlag>$terminalFlag</terminalFlag>
    <commentRes></commentRes>
	<reserved></reserved>
</message>";

            DateTime dt = DateTime.Now;
            xmlRequest = string.Format(xmlRequest, dt.ToString("yyyyMMddHHmmss"), Common.TraceNo_CITIC,
                PaymentEntity_CITIC.terminalID, PaymentEntity_CITIC.merchantID, PaymentEntity_CITIC.merchantName, batchNo);
            string strDataSet = "";
            ArrayList arrayTransID = new ArrayList();
            int i = 1, countFailed = 0;
            string xml = xmlRequest;

            try
            {
                foreach (DataRow dr in ds.Tables[0].Rows)
                {
                    Model.T_CITIC_Transfer tran = ObjectConvertor.ToObject<Model.T_CITIC_Transfer>(dr);

                    arrayTransID.Add(tran.PosID);

                    string data = tran.MerchantID + tran.TerminalID + tran.BatchNo + tran.TransDate + tran.TransTime + tran.PAN.PadRight(19, ' ')
                        + Common.CITICAmountFormat(tran.TransAmt) + tran.CurrCode + tran.SystemRefCode + tran.PosID
                        + tran.AuthorizeCode + tran.ProductCode + tran.DividedMonths + (tran.TransType == "退款" ? "Y" : " ");

                    strDataSet += System.Environment.NewLine + "    <record>" + data.PadRight(150, ' ') + "</record>";
                    totalTrsCnt--;
                    i++;

                    if (i > 20)
                    {
                        xml = xml.Replace("<dataSet>", "<dataSet count=\"20\">");
                        xml = xml.Replace("$dataSet", strDataSet);
                        xml = xml.Replace("$terminalFlag", totalTrsCnt == 0 ? "Y" : "N");
                        this.XMLSent = xml;
                        xml = CITIC_BANK.checkAccount(xml);
                        this.XMLReceived = xml;
                        string retCode = Common.GetXMLElementValue(xml, "retCode");

                        if (retCode != "0000000")
                        {
                            this.ErrorMsg = "对账失败，返回码是：" + retCode + "，反馈信息是：" + Common.GetXMLElementValue(xml, "commentRes");
                            LogIt(this.ErrorMsg, "对账");
                            return;
                        }
                        else
                        {
                            XmlDocument xd = new XmlDocument();
                            xd.LoadXml(xml);
                            XmlNodeList xnDataSet = xd.SelectNodes("message/dataSet/record");
                            foreach (XmlNode xn in xnDataSet)//被返回的条目
                            {
                                data = xn.InnerText;
                                string transDate = data.Substring(29, 8);
                                string transTime = data.Substring(37, 8);
                                string traceNo = data.Substring(92, 6);
                                string flag = data.Substring(113, 1);
                                flag = CheckFlag(flag);

                                Common.DB.Update(Tables.t_CITIC_Transfer)
                                    .AddColumn(Tables.t_CITIC_Transfer.Flag, flag)
                                    .Where(Tables.t_CITIC_Transfer.TransDate == transDate)
                                    .Where(Tables.t_CITIC_Transfer.TransTime == transTime)
                                    .Where(Tables.t_CITIC_Transfer.PosID == traceNo)
                                    .Execute();

                                flag = string.Format("核对失败，批号：{0} 流水号：{1} 状态：{2}", batchNo, traceNo, flag);
                                LogIt(flag, "对账");

                                arrayTransID.Remove(traceNo);//移除对账失败的条目
                                countFailed++;
                            }

                            try
                            {
                                Common.DB.Update(Tables.t_CITIC_Transfer)
                                    .AddColumn(Tables.t_CITIC_Transfer.Flag, "对账成功")
                                    .Where(Tables.t_CITIC_Transfer.PosID.In(arrayTransID.ToArray()))
                                    .Execute();
                            }
                            catch (Exception ex)
                            {
                                string msg = "更新对账状态失败，流水号：{0} 错误：{1}";
                                string strTraceID = "";
                                foreach (object obj in arrayTransID)
                                    strTraceID += obj.ToString() + ",";
                                msg = string.Format(msg, strTraceID, ex.Message);
                                LogIt(msg, "对账");
                            }

                            strDataSet = "";
                            i = 1;
                            xml = xmlRequest;//重新来！！
                        }
                    }
                }

                if (i != 1)//如果i=1就是临界值，刚好是20条！
                {
                    xml = xml.Replace("<dataSet>", string.Format("<dataSet count=\"{0}\">", i - 1));
                    xml = xml.Replace("$dataSet", strDataSet);
                    xml = xml.Replace("$terminalFlag", "Y");
                    this.XMLSent = xml;
                    xml = CITIC_BANK.checkAccount(xml);
                    this.XMLReceived = xml;
                    string retCode2 = Common.GetXMLElementValue(xml, "retCode");

                    if (retCode2 != "0000000")
                    {
                        this.ErrorMsg = "对账失败，返回码是：" + retCode2 + "，反馈信息是：" + Common.GetXMLElementValue(xml, "commentRes");
                        LogIt(this.ErrorMsg, "对账");
                        return;
                    }
                    else
                    {
                        XmlDocument xd = new XmlDocument();
                        xd.LoadXml(xml);
                        XmlNodeList xnDataSet = xd.SelectNodes("message/dataSet/record");
                        foreach (XmlNode xn in xnDataSet)
                        {
                            string data = xn.InnerText;
                            string transDate = data.Substring(29, 8);
                            string transTime = data.Substring(37, 8);
                            string traceNo = data.Substring(92, 6);
                            string flag = data.Substring(113, 1);
                            flag = CheckFlag(flag);

                            Common.DB.Update(Tables.t_CITIC_Transfer)
                                   .AddColumn(Tables.t_CITIC_Transfer.Flag, flag)
                                   .Where(Tables.t_CITIC_Transfer.TransDate == transDate)
                                   .Where(Tables.t_CITIC_Transfer.TransTime == transTime)
                                   .Where(Tables.t_CITIC_Transfer.PosID == traceNo)
                                   .Execute();

                            flag = string.Format("核对失败，批号：{0} 流水号：{1} 状态：{2}", batchNo, traceNo, flag);
                            LogIt(flag, "对账");

                            arrayTransID.Remove(traceNo);//移除对账失败的条目
                            countFailed++;
                        }

                        try
                        {
                            Common.DB.Update(Tables.t_CITIC_Transfer)
                                .AddColumn(Tables.t_CITIC_Transfer.Flag, "对账成功")
                                .Where(Tables.t_CITIC_Transfer.PosID.In(arrayTransID.ToArray()))
                                .Execute();
                        }
                        catch (Exception ex)
                        {
                            string msg = "更新对账状态失败，流水号：{0} 错误：{1}";
                            string strTraceID = "";
                            foreach (object obj in arrayTransID)
                                strTraceID += obj.ToString() + ",";
                            msg = string.Format(msg, strTraceID, ex.Message);
                            LogIt(msg, "对账");
                        }
                    }
                }

                Common.hasSettled = true;
                this.ErrorMsg += System.Environment.NewLine + string.Format("供对账 {0} 条，其中失败 {1} 条！", totalBackup, countFailed);
                LogIt(this.ErrorMsg, "对账");
            }
            catch (Exception ee)
            {
                this.ErrorMsg = ee.Message;
                LogIt(this.ErrorMsg, "对账");
            }
        }

        /// <summary>
        /// 标志位的中文解释
        /// </summary>
        /// <param name="flag"></param>
        /// <returns></returns>
        string CheckFlag(string flag)
        {
            switch (flag)
            {
                case "A":
                    return "核对成功";
                case "B":
                    return "已核对";
                case "C":
                    return "核对失败";
                case "D":
                    return "不存在";
                case "R":
                    return "已撤销";
                case "M":
                    return "金额不合";
                case "T":
                    return "流水号不合";
                default:
                    return "n/a";
            }
        }

        public void MaintainSession()
        {
            try
            {
                string xml = CITIC_BANK.maintainSession("hello");
                this.XMLReceived = xml;
            }
            catch (Exception ee)
            {
                this.ErrorMsg = ee.Message;
            }
        }

        void LogIt(string content, string logType)
        {
            try
            {
                Common.DB.Insert(Tables.t_CITIC_Log)
                   .AddColumn(Tables.t_CITIC_Log.LogContent, content)
                   .AddColumn(Tables.t_CITIC_Log.LogTime, DateTime.Now)
                   .AddColumn(Tables.t_CITIC_Log.LogType, logType)
                   .Execute();
            }
            catch{}
        }
    }
}
